
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

#ifdef USE_MPI
#include <mpi.h>
#endif

#include "galite/GAGenome.h"

#ifndef _ga_population_h_
#define _ga_population_h_

#define MAX_POP_SIZE 2048

bool cmpGenome(GAGenome *a, GAGenome *b);

class GAPopulation 
{
 protected:

  vector<GAGenome*> indiv;	
  float fitSum, fitAve;		// sum, ave of the population's fitness scores
  float fitMax, fitMin;		// max, min of the population's fitness scores

 public:

  GAPopulation(): fitSum(0), fitAve(0), fitMax(0), fitMin(0) {}

  GAPopulation(const GAGenome *c, unsigned int psize); 

  GAPopulation(unsigned int psize);

  void initialize(const GAGenome *c, unsigned int popsize); 

  virtual ~GAPopulation() {
	clear();
	}

  void evaluate();

  void print()
	{
	for (unsigned int i=0; i<indiv.size(); i++) {
		cout << "Chromosome " << i << ": " << indiv[i]->evaluate() << endl;
		}
	}

  void clear()
	{
	for (unsigned int i=0; i<indiv.size(); i++) {
		if (!indiv[i]->isAlive()) {
			cout << "Deleting indiv " << indiv[i]->getId() << endl;
			assert (indiv[i] != NULL);
			delete indiv[i];
			}
		else
			cout << "Not deleting indiv " << indiv[i]->getId() << endl;
		}
			
	indiv.clear();
	}

  void makeDead() {
	for (unsigned int i=0; i<indiv.size(); i++) {
		indiv[i]->setDead();
		}	
        }

  void add(GAGenome* g) {
    indiv.push_back(g);
    }

  void sort() 
	{
        std::sort(indiv.begin(), indiv.end(), cmpGenome);
	}

  void stats();

  GAGenome& individual(unsigned int i) const
    	{ 
	 return *indiv[i]; 
	}

  int size() const 
	{ 
	return indiv.size(); 
	}

  float fitsum() const 
	{ 
	return fitSum;
	}

  float fitave() const 
	{ 
	return fitAve;
	}

  float fitmax() const 
	{ 
	return fitMax;
	}

  float fitmin() const 
	{ 
	return fitMin;
	}

  GAGenome& best() const
	{
	return *indiv[0];
  	}
  
};


#endif
